#ifndef __CINT__
#include <TString.h>
#include <TFile.h>
#include <TStopwatch.h>
#include <TAlienCollection.h>
#endif
Int_t stage(TString mode = "normal" , TString inputFileName = "myfile.txt", TString redirectorName = "prf001-iep-grid.saske.sk", TString xmlAppend = "AliESDs.root")
{

  TStopwatch timer;
  timer.Start();

  // if input is xml, then convert it in to txt

  if (inputFileName.EndsWith(".xml"))
    if (ConvertXML2TXT(inputFileName, redirectorName, xmlAppend) < 0) return -1;

  inputFileName.ReplaceAll(".xml", ".txt");
  inputFileName.ReplaceAll(".txt", "");

  CleanOKAndBadFiles(inputFileName);


  ofstream fileOKFiles(Form("%s_OK.txt", inputFileName.Data()));
  if (!fileOKFiles) {
    Error("stageTXT.C", Form("Cannot open file %s", inputFileName.Data()));
    return kFALSE;
  }

  ofstream fileBadFiles(Form("%s_BAD.txt", inputFileName.Data()));
  if (!fileBadFiles) {
    Error("stageTXT.C", Form("Cannot open file %s", inputFileName.Data()));
    return kFALSE;
  }

  if (!mode.CompareTo("async"))
    StageAsync(inputFileName, fileOKFiles, fileBadFiles);
  else
    StageNormal(inputFileName, fileOKFiles, fileBadFiles);

  fileOKFiles.close();
  fileBadFiles.close();

  timer.Stop();
  timer.Print();

  return 0;
}

Int_t ConvertXML2TXT(TString xmlFile = "my.xml", TString redirectorName = "prf001-iep-grid.saske.sk", TString xmlAppend = "AliESDs.root")
{


  TAlienCollection *myCollection = TAlienCollection::Open(xmlFile.Data());
  if (!myCollection) {
    Error("ConvertXML2TXT.C", Form("Cannot open AliEn collection %s !!!", xmlFile.Data()));
    return -1;
  }

  TString outFilename = xmlFile.Data();

  outFilename.ReplaceAll("xml", "txt");
  ofstream file(outFilename, ios::out);

  if (!file.is_open()) {
    Error("ConvertXML2TXT.C", Form("File %s was not created !!!", outFilename.Data()));
    return -2;
  }

  // initialize a counter to check the number of read files
  UInt_t numOfFiles = myCollection->GetNofGroups();

  TString filename;

  while (myCollection->Next()) {
    filename = myCollection->GetTURL("");
    filename.ReplaceAll("alien:///", Form("root://%s//", redirectorName.Data()));
    filename += "#";
    filename += xmlAppend.Data();
    file << filename.Data() << endl;
  }

  file.close();

  Info("ConvertXML2TXT", Form("Converted %s to %s ...", xmlFile.Data(), outFilename.Data()));

  return 0;
}

void CleanOKAndBadFiles(TString fileName)
{
  gSystem->Exec(Form("rm -f %s_OK.txt", fileName.Data()));
  gSystem->Exec(Form("rm -f %s_BAD.txt", fileName.Data()));
}

Int_t StageNormal(TString filename, ofstream & fileOk, ofstream & fileBad)
{

  ifstream fileIn;
  fileIn.open(Form("%s.txt", filename.Data()));

  Int_t numOk = 0, numBad = 0;
  TFile *f;
  TString file;

  while (fileIn.good()) {
    fileIn >> file;

    if (file.IsNull()) continue;

    Printf(Form("Opening %s", file.Data()));
    f = TFile::Open(file.Data());
    if (f) {
      fileOk << file.Data() << endl;
      numOk++;
    }
    else {
      fileBad << file.Data() << endl;
      numBad++;
    }

    delete f;
  }

  fileIn.close();

  Info("StageNormal", Form("Bad files : %d out of %.0f", numBad, (Double_t)numBad + numOk));
  return 0;
}

Int_t StageAsync(TString filename, ofstream & fileOk, ofstream & fileBad, Int_t numberFilesOpenedAtOnce = 100)
{

  gSystem->Load("libNetx");
  ifstream fileIn;
  fileIn.open(Form("%s.txt", filename.Data()));

  TObjArray array;
  TFileOpenHandle *foh = 0;

  Int_t numOk = 0, numBad = 0;
  TFile *f;
  TString file;

  while (fileIn.good()) {
    fileIn >> file;

    if (file.IsNull()) continue;

    Printf(Form("Opening Async %s", file.Data()));
    foh = TFile::AsyncOpen(file.Data());
    if (foh)
      array.Add((TObject*)foh);
  }

  fileIn.close();

  TIter myiter(&array);
  while ((foh = (TFileOpenHandle *)myiter.Next())) {
    if (foh) {
      f = TFile::Open(foh);
      if (f) {
        Printf(Form("%s is opened", f->GetName()));
        fileOk << f->GetName() << endl;
        numOk++;
      }
      else {
        fileBad << f->GetName() << endl;
        numBad++;
      }
    }
  }

  Info("StageAsync", Form("Bad files : %d out of %.0f", numBad, (Double_t)numBad + numOk));

  return 0;
}
